﻿/*
	author:wanghaixin@jd.com
	date:20130320
	ver:v1.0.0
	
	description:
	
*/


/*
 *  extending of original object
 */



/*
each is similar to Array object's foreach API in JS 1.6. 
@param : handler which acts on the elements in the array
return : no
*/
Array.prototype.each = function(fun){
	if(!fun.constructor == Function) return;
		for(var i = 0, len = this.length;i <len; i++) fun.call(this,i,this[i]);
}; 

Array.prototype.isIn = function(arg){
	for(var i = this.length; i > 0; i--){
		if(this[i-1] == arg)
			return true;
	}
	return false;
};

/*
 * 或者在数组中的位置
 */
Array.prototype.getIndex = function(arg){
	for(var i = 0, len = this.length; i < len; i++){
		if(this[i] == arg)
			return i;
	}
	return -1;
};

/*
 * 数组过滤，过滤在另一数组中存在的数据
 */
Array.prototype.aUnique = function(arr){
	if(arr.constructor != Array)
		throw new Error('Array.aUnique:arguments error!');
	var _result = [];
	for(var i = 0, len = arr.length; i < len; i++){
		if(!this.isIn(arr[i]))
			_result.push(arr[i]);
	}
	return _result;
};

/*
 * 去除数组中某个元素
 */
Array.prototype.del= function(ele){
	  var index = this.getIndex(ele);
      if(index != -1){
            this.splice(index,1);
      }
      return this;	
};


(function($,w){

	$(function(){
		/*
		 * no-margin logics
		 */
		function _no_margin_handle(){
			$('.J-layout').each(function(index,n){
				var m = $(n),_flag = true;
				m.children('div').each(function(index,n){
					if($(n).children('[instanceid]').length)
						_flag = false;
				});
				if(!_flag)
					m.parents('.J-layout-area').addClass('no-margin');
			});
		}
		/*
		 * 背景锁定功能
		 */
		function _background_fixed_handle(){
			if($('.layout-main').length){
				var _is_fixed = parseInt($('.layout-main').attr('isfixed')),
				_TOP = $('.layout-main').offset().top,
				_decorate_flag = typeof gConfig != 'undefined';
			}
			
			
			if(_is_fixed){
				$(_decorate_flag?'.layout-container':window).scroll(function(){
					var __top = $(this).scrollTop();

					if(__top >= _TOP){
						$('.layout-main').css('background-attachment','fixed');
					}
					else{
						$('.layout-main').css('background-attachment','scroll');
					}
				});
			}
			
		}
		_no_margin_handle();
		_background_fixed_handle();
	});
	w.window2013CSS = function(obj,css){
		var _css = css,
			_mutant_css = gBase.JSONClone(css),
			_side_bar = $('#slide_bar_area'),
			_extra_value = _side_bar.length&&!_side_bar.hasClass('off')?185:0;
		if(!$('#slide_bar_area').length){
			obj.css(_css);
			return;
		}
		if(_mutant_css.left){
			_mutant_css.left = _mutant_css.left.match(/%/g)?($(window).width() + _extra_value)*parseInt(_mutant_css.left)/100 + 'px':_mutant_css.left; 
		}
		if(_mutant_css.right){
			_mutant_css.right = _mutant_css.right.match(/%/g)?($(window).width() - _extra_value)*parseInt(_mutant_css.right)/100 + 'px':_mutant_css.right;
		}
		if(typeof gBase.fGetUrlParms()['veBean.open'] == 'undefined' || gBase.fGetUrlParms()['veBean.open'] === '1'){
			obj.css(_mutant_css);
		}
		else{
			obj.css(_css);
			
		}
		$(window).bind('sidebarchange',function(e,collapse){
			if(collapse){
				obj.css(_mutant_css);
			}
			else{
				obj.css(_css);
			}
		});
	};
	
	w.window2013scroll = function(handler){
		if($('#slide_bar_area').length){
			$('.J-layout-container').scroll(function(){
				handler.call(this);
			});
		}
		else{
			$(window).scroll(function(){
				handler.call(this);
			});
		}
	};
	
	w.window2013scrollTop = function(){
		return $('#slide_bar_area').length?$('.J-layout-container').scrollTop():$(window).scrollTop();
	};
})(jQuery,window);/*
 * author:wanghaixin@jd.com
 * date:2013-04-11
 * ver:v1.0.0
 */

/*
 * 伪属性模块加载框架
 */
(function($,w){
	w.jshop = {};
	w.jshop.module = {};
	
	$.extend(w.jshop.module,{
		/*
		 * 去除图片懒加载
		 */
		 ridLazy : function(obj) {
			$(obj).find('img.J_imgLazyload').each(function(){
				$(this).attr('src',$(this).attr('original'));
				$(this).removeAttr('original');
				$(this).removeClass('J_imgLazyload');
			});	
		},
		/*
		 * 旧方法，和changeClass一样。
		 */
		changeStyle:function(args){
			var param = $.extend({node:'li', defaultClass:'jCurrent', defaultShow:0}, args),
				elem = $(this).find(param.node),
				defaultClass = param.defaultClass,
				defaultShow = param.defaultShow;
			
			elem.eq(defaultShow).addClass(defaultClass);
			
			elem.each(function(index,n){
				$(n).mouseover(function(e){
					$(this).addClass(defaultClass).siblings().removeClass(defaultClass);
				});
			});
		},
		/*
		 * @function：改变样式：默认显示一个，鼠标移动到节点上时增加当前样式，同时去除其兄弟节点的当前样式
		 * @description：主要应用于190布局宽度下，因宽度有限，默认只显示商品标题，当鼠标移动到标题上时显示更多的商品信息。
		 * @param：如{node:'li', defaultClass:'jCurrent', defaultShow:0}。参数node为单个节点名；参数defaultClass可任意命名，只要css里面有这个名字。
		 * @author：20130114 by bjwanchuan
		 */
		changeClass:function(args){
			var param = $.extend({node:'li', defaultClass:'jCurrent', defaultShow:0}, args),
				elem = $(this).find(param.node),
				defaultClass = param.defaultClass,
				defaultShow = param.defaultShow;
			
			elem.eq(defaultShow).addClass(defaultClass);
			
			elem.each(function(index,n){
				$(n).mouseover(function(e){
					$(this).addClass(defaultClass).siblings().removeClass(defaultClass);
				});
			});
		},
		/*
		 * @function：切换样式：鼠标移动到节点上时增加一个样式，移出时去除增加的样式
		 * @description：主要应用于商品列表类模块，如商品推荐、分页显示商品等模块，默认显示商品图片等，鼠标移动上去时显示更多商品信息。
		 * @param：如{node:'li', defaultClass:'current', defaultShow:0}。参数node为单个节点名；参数defaultClass可任意命名，只要css里面有这个名字。
		 * @author：20130114 by bjwanchuan
		 */
		tabClass:function(args){
			var param = $.extend({node:'li', defaultClass:'current'}, args),
				elem = $(this).find(param.node).length ? $(this).find(param.node) : $ (this),
				defaultClass = param.defaultClass,
				defaultShow = param.defaultShow;
				
			if(defaultShow){
				elem.eq(defaultShow).addClass(defaultClass);
			}
			
			elem.bind({
				mouseenter:function(){
					$(this).addClass(defaultClass).siblings().removeClass(defaultClass);
				},
				mouseleave:function(){
					$(this).removeClass(defaultClass);
				}
			});
		},
		/*
		 * @function：切换：鼠标移动到不同的tab，切换相对应的内容
		 * @description：主要应用在商品分类推荐模块中，点击不同的标题，切换相对应的内容。
		 * @param：如{tabNode:'.jSortTab span', tabContent:'.jSortContent ul', arrow:'.jSortTabArrow', defaultClass:'current, setUpWidth:0}。setUpWidth值：0，1；其中0表示平均分配宽度，1表示默认宽度；
		 * @author：20130114 by bjwanchuan
		 */
		tab:function(args){
			var param = $.extend({tabNode:'.jSortTab span', arrow:'.jSortTabArrow', defaultClass:'current', tabContent:'.jSortContent ul'}, args),
				_this = this,
				tabNode = $(_this).find(param.tabNode),
				tabContent = $(_this).find(param.tabContent),
				arrow = $(_this).find(param.arrow);
				
			//初始化结构
			tabNode.eq(0).addClass(param.defaultClass);
			tabContent.eq(0).addClass(param.defaultClass);
			tabNode.each(function(i,n){
				$(n).attr('data-num',i);
			});
			
			var width = 0;
			//自适应宽度
			if(param.setUpWidth) {
				if(tabNode.width() > 0) {
					width = tabNode.width();
				}else{
					width = (tabNode.parent().parent().width()-0.03)/tabNode.length;	
				}
			}else{
				width = (tabNode.parent().parent().width()-0.03)/tabNode.length;
			}
			tabNode.css({width: width});
			arrow.css({width: width});
			
			//绑定鼠标移动事件
			tabNode.bind({
				mouseenter: function(){
					$(this).addClass(param.defaultClass).siblings().removeClass(param.defaultClass);
					tabContent.eq($(this).attr('data-num')).addClass(param.defaultClass).siblings().removeClass(param.defaultClass);
					arrow.animate({left:($(this).attr('data-num'))*width},300,function(){});
				}
			});
		},
		/*
		 * @function：切换显示：通过触发一个元素，切换其他元素的显示。可选择闭环切换、前进后退及随机切换显示。
		 * @description：可应用于任意模块，只要有使用场景。
		 * @param：如{eventNode:'.jClick', parentNode:'.jSortContent', childNode:'ul', defaultClass:'current', eventType:'click', num:0, tabTime:500, subFunction:'circle'}
		 * eventNode触发切换的节点；parent切换节点的父节点；child切换节点；defaultClass显示样式；eventType触发的事件类型；
		 * num初始显示第几个；tabTime每一屏切换的时间；subFunction显示方式：闭环circle、前进倒退direction、随机random；
		 * @author：20140117 by bjwanchuan
		 */
		tabShow : function(args){
			var param = $.extend({eventNode:'.jClick', parentNode:'.jSortContent', childNode:'ul', defaultClass:'current', eventType:'click', num:0, tabTime:500, subFunction:'circle'},args),
				_this = $(this),
				eventNode = _this.find(param.eventNode),//触发切换的节点
				parent = _this.find(param.parentNode),//切换节点的父节点
				child = _this.find(param.childNode),//切换节点
				defaultClass = param.defaultClass,//显示样式
				eventType = param.eventType,//触发的事件类型
				num = (param.num === Number && param.num <= len) ? param.num : 0,//初始显示第几个
				tabTime = param.tabTime,//每一屏切换的时间
				subFunction = param.subFunction,//显示方式：闭环circle、前进倒退direction、随机random
				len = child.length,
				isLeft = true;
				
			//初始化显示
			child.eq(num).addClass(defaultClass);
			
			//事件触发
			eventNode[eventType](function(){
				if(param.subFunction){
					showStyle[param.subFunction].call(_this);
				}
				callBack();
			});
			
			var showStyle = {
				circle : function(){
					num = (num + 1)%len;
				},
				direction : function(){
					if(isLeft){
						num++;
						if(num == len - 1){
							isLeft = false;
						}
					}else{
						num--;
						if(num  == 0){
							isLeft = true;
						}
					}	
				},
				random : function(){
					num = parseInt(Math.random() * len);
				}
			}
			
			function callBack(){
				child.eq(num).addClass(defaultClass).siblings().removeClass(defaultClass);
				child.animate({opacity:0},0,function(){});
				child.eq(num).animate({opacity:1},param.tabTime,function(){});	
			}
		},
		/*
		 * @function：自适应布局：根据布局的宽度判断能放下的一行数量，并将平均宽度转化为百分比形式。转化好的class类将自动写入节点。
		 * @description：主要应用于不同的宽度布局，如190、390、590、790、990等布局，同一套模板显示的列表个数会根据布局宽度自动计算，并撑满布局。这个方法和autoWidth类似，各有各的使用效果。
		 * @param：如{node:'li', spacingType:'margin', size:1}。node为需要计算宽度的节点；spacingType为节点的间距类型，其值为：margin和padding；size为间距的宽度，其值为0.5和1，其中0.5代表左右间距为0.5%，1代表左右间距为1%。
		 * @author：20130114 by bjwanchuan
		 */
		autoLayout : function(args){
			var _para = $.extend({node: 'li', spacingType: 'margin', size: 1},args || {}),
				_this = $(this),
				_elem = _this.find(_para.node),
				_qty = parseInt(_elem.parent().parent().width()/_elem.outerWidth(true)),
				_ie = $.browser.msie&&parseInt($.browser.version) <= 10?'i':'',
				_spacing = _para.spacingType.match(/^m/)?'m':'p',
				_size = _para.size == 0.5?'OneHalf':'One',
				_arr = ['qOne','qTwo','qThree','qFour','qFive','qSix','qSeven','qEight','qNine','qTen','qEleven','qTwelve'];
			
			_elem.addClass(_ie + _arr[_qty-1] + _size).addClass(_spacing + _size);
		},
		/*
		 * @function：自适应宽度：根据布局的宽度判断能放下的一行数量，并将多余的宽度平均分配给每一个列表项。支持css对象传入。
		 * @description：主要应用于不同的宽度布局，如190、390、590、790、990等布局，同一套模板显示的列表个数会根据布局宽度自动计算，并撑满布局。
		 * @param：如{node:'li', extra:{margin:'0 5px', padding:'5px 0'}}。node为需要计算宽度的节点；extra为给需要计算宽度的节点增加一些css样式，这样可适应不同的效果需求。
		 * @author：20130114 by bjwanchuan
		 */
		autoWidth:function(args){
			var _para = $.extend({node:'li', extra:{}}, args || {}),
				_this = this,
				elems = $(_this).find(_para.node), 
				elem = elems.eq(0);
			
			elems.css(_para.extra);
			
			var outerWidth = parseInt(elem.data('outerWidth') || elem.outerWidth(true)),
				width = parseInt(elem.data('width') || elem.css('width')),
				qty = parseInt(elem.parent().parent().width()/outerWidth);
			
			elem.data({'outerWidth':outerWidth, 'width':width});
			
			var extraWidth = outerWidth - width;
			var newWidth = (elem.parent().parent().width()-extraWidth*qty-0.03)/qty;
			elems.css({width:newWidth});
		},
		/*
		 * @function：平均宽度：根据父节点宽度，平均分配子节点宽度。
		 * @description：主要应用于导航、商品分类推荐等模块中。避免因数量较少而容器右边出现空白的情况。
		 * @param：如{equallyNode:'.jSortTab span', equallyParentNode:null}。equallyNode需要平均父级宽度的节点；equallyParentNode为父级节点，如果此参数没传则默认为当前引用此方法的节点。
		 * @author：20130114 by bjwanchuan
		 */
		equallyWidth:function(args){
			var param = $.extend({equallyNode:'.jSortTab span', equallyParentNode:null}, args),
				_this = $(this),
				nodeParent = (_this.find(param.equallyParentNode).length > 0) ? _this.find(param.equallyParentNode) : _this,
				elems = _this.find(param.equallyNode),
				elem = elems.eq(0);
			
			var outerWidth = parseInt(elem.data('outerWidth') || elem.outerWidth(true)),
				width = parseInt(elem.data('width') || elem.css('width')),
				qty = elems.length;
			
			elem.data({'outerWidth':outerWidth, 'width':width});
			
			var extraWidth = outerWidth - width;
			var newWidth = (nodeParent.width()-extraWidth*qty-0.03)/qty;
			elems.css({width:newWidth});
		},
		/*
		 * @function：100%高度：用在相对定位里面有绝对定位时，背景透明图层以父节点为基准将高度撑满。
		 * @description：主要应用于不同尺寸图片需要遮罩的效果中，由于高度100%存在浏览器兼容，这个方法会自动获取传入的基准容器高度，并赋给遮罩层。
		 * @param：如{fullHeightNode:'li', fullNode:'.jShade'}。fullHeightNode需要参照高度的基准节点；fullNode需要撑满高度的遮罩节点。
		 * @author：20130114 by bjwanchuan
		 */
		fullHeight:function(args){
			var param = $.extend({fullHeightNode:'li', fullNode:'.jShade'}, args),
				elem = $(this).find(param.fullHeightNode),
				fullNode;
			
			elem.bind({
				mouseenter:function(){
					fullNode =$(this).find(param.fullNode);
					fullNode.css({height:$(this).height()});
					
				}
			});
		},
		/*
		 * @function：瀑布流：将图片或商品列表错位布局，错位高度可设置。
		 * @description：主要应用于图片或商品列表类模块，如商品推荐、图片show等模块。
		 * @param：如{area:'.goodsArea', node:"li", topSpac:10}。area需要重设高度的父级节点；node需要使用瀑布流的节点；topSpac顶部错位的距离。
		 * @author：20130114 by bjwanchuan
		 */
		waterfallFlow:function(args){
			var param = jQuery.extend({area:'.goodsArea', node:"li", topSpac:10}, args),
		   		_this = $(this),
				area = _this.find(param.area),
				elem = _this.find(param.node),
				outerWidth = parseInt(elem.data('outerWidth') || elem.outerWidth(true)),
				qty = parseInt(elem.parent().width()/outerWidth),
				topPos,
				array = [];
				elem.data({'outerWidth':outerWidth});
				
		   elem.each(function(index, e){
			   //获取行数
				var row = parseInt(index/qty),
					//获取列数：通过每一个的位置除去每一行的数量，剩下的余数就是每一列
					col = index%qty,
					//获取每一个的左边距：离最左边的距离
					leftPos = col*jQuery(e).outerWidth(true);
				
				//如果是第一行
			   if(row == 0){
				   topPos = parseInt((col%2)*param.topSpac);
			   }
			   else{
				   var topNode = jQuery(elem.get((row-1)*qty+col));
				   topPos = topNode.outerHeight(true)+parseInt(topNode.css("top"));
			   }
			   jQuery(e).css({left:leftPos,top:topPos});
				
				//将每一个的top和自身的高度之和保存到数组里
				array.push(parseInt(jQuery(e).css("top"))+jQuery(e).outerHeight(true));
		   });
			
			//数组排序，获取最大的高度
			function compare(value1, value2){
				if(value1<value2){
					return -1;
				}else if(value1>value2){
					return 1;
				}else{
					return 0;
				}
			}
			array.sort(compare);
			
			//重设父级的高度，以达到背景自适应
			area.css("height",array[array.length-1]);
	   },
		/* 
		 * @function 图片轮播：1、根据用户设置的宽度和高度来确定轮播图的大小。2、可自定义向左、向上轮播和渐变轮播参数。3、可设置图片轮播时间。
		 * @description 主要应用于图片轮播模块。
		 * @param：
		 * @author 20130114 by bjwanchuan
		 */
		slidePhoto:function(args){
			
			// 定义传入的CSS调用变量
			var _this=this,
				param=$.extend({imgArea:'.jbannerImg', imgNodeArea:'.jImgNodeArea', imgNode:'.jbannerImg dl', tabArea:'.jbannerTab', tabNode:'.jbannerTab span', photoName:'.jDesc', arrowLeft:'.jPreOut', arrowRight:'.jNextOut', arrowLeftOver:'jPreOver', arrowRightOver:'jNextOver', defaultClass:'show', slideDirection:'left', timer:'3', subFunction:'transparentEffect', eventType:'click',showArrow:1}, args),
				imgArea = $(_this).find(param.imgArea),
				imgNode = $(_this).find(param.imgNode),
				tabArea = $(_this).find(param.tabArea),
				tabNode = $(_this).find(param.tabNode),
				photoName = $(_this).find(param.photoName),
				defaultClass = param.defaultClass,
				eventType = param.eventType,
				timer = !param.timer*1000?3000:param.timer*1000,
				scroll,
				imgNodeArea = $(_this).find(param.imgNodeArea),
				isFull = param.isFull;
			
			//全局变量
			var index = 0,direction = 1,time = null,moveRange = 0,partTime = null,animate = null;
			if(!imgNode.length) return;
			
			/**
			 * 轮播图所有效果
			 */
			var banner = {
				transparentEffect : function(){
					//初始化
					$(_this).css({'background-color':imgNode.eq(index).attr('background')});
					
					// 调用函数
					init();
					triggerThumbnail();
					triggerDirection();
					if(param.showArrow!=1){triggerArrow();}
					animate = transparent;
					time = setTimeout(imgMove, timer);
				},
				moveEffect : function(){
					var isTop = (param.slideDirection == 'top')?true:false;
					scroll = (isTop)?"scrollTop":"scrollLeft";
					
					//初始化
					$(_this).css({'background-color':imgNode.eq(index).attr('background')});
					if(isTop){
						imgNodeArea.css({height:20000, width:$(_this).width()});
						imgNode.css({width:imgNodeArea.width(),height:"auto","float":"none"});
						moveRange = imgNode.height();
						imgArea[0][scroll] = index * moveRange;
					}else{
						imgNodeArea.css({width:20000});
						imgNode.css({width:imgNode.find("img").width(),height:"100%","float":"left"});//将这个宽度写在css里，在ie6下面，获取到的父级宽度是被这个元素撑开的宽度
						moveRange = imgNode.width();
						imgArea[0][scroll] = index * moveRange;
					};
					
					// 调用函数
					init();
					triggerThumbnail();
					triggerDirection();	
					if(param.showArrow!=1){triggerArrow();}
					animate = oneImgMove;
					time = setTimeout(imgMove, timer);
				}
			};
			
			/**
			 * 根据传入的子方法名执行对应的子方法
			 */
			if(banner[param.subFunction])
				banner[param.subFunction].call(_this);
			
			/**
			 * 轮播图初始化
			 */
			function init(){
				$(_this).css({cursor:'pointer'});
				imgArea.css({width:imgNode.find("img").width(),height:imgNode.find("img").height()});
				imgNode.eq(0).addClass(defaultClass);
				tabNode.eq(0).addClass(defaultClass);
				photoName.text(imgNode.eq(0).find("img").attr("title"));

				$(_this).click(function(){
					window.open(imgNode.eq(index).attr('ref'));
				});
				
				autoMiddle();
				$(window).resize(function(){
					autoMiddle();
				});
			}
			
			/**
			 * 轮播图自适应居中于屏幕中间
			 */
			function autoMiddle(){
				var extra = imgArea.width()-$(_this).width();
				if(extra>0){
					imgArea.css({'margin-left':-extra/2});
				}else{
					imgArea.css('margin','0 auto');
				}
			}
			
			/**
			 * 给每个tab缩略图绑定事件
			 */ 
			function triggerThumbnail(){
				tabNode.each(function(i,elem){
					$(elem)[eventType](function(){
						imgNode.eq(index).removeClass(defaultClass);
						tabNode.eq(index).removeClass(defaultClass);
						index = i;
						imgNode.eq(index).addClass(defaultClass);
						tabNode.eq(index).addClass(defaultClass);
						photoName.text(imgNode.eq(index).find("img").attr("title"));
						animate();
						return false;
					});
				});
			}
			
			/**
			 * 点击箭头或数字时，重置时间
			 */
			function _stop(){
				clearTimeout(time);
				time = null;
				clearTimeout(partTime);
				partTime = null;
				imgNodeArea.clearQueue();
				imgNode.eq(index).clearQueue();
			}
			
			/**
			 * 切换图片和缩略图
			 */ 
			function imgMove(){
				if (direction == 1){
					if (index < imgNode.length - 1){
						classOper([imgNode,tabNode],defaultClass,true);
					}else{
						direction = 0;
						classOper([imgNode,tabNode],defaultClass,false);
					}
				}else{
					if (index > 0){
						classOper([imgNode,tabNode],defaultClass,false);
					}else{
						direction = 1;
						classOper([imgNode,tabNode],defaultClass,true);
					}
				}
				photoName.text(imgNode.eq(index).find("img").attr("title"));
				animate();
			}
			
			/**
			 * 鼠标移动显示左右移动箭头
			 */
			function triggerArrow(){
				var arrowLeft = $(_this).find(param.arrowLeft),arrowRight = $(_this).find(param.arrowRight);
				$(_this).bind({
					mouseover:function(){
						arrowLeft.show();
						arrowRight.show();
					},
					mouseout:function(){
						arrowLeft.hide();
						arrowRight.hide();
					}
				 });
			}
			
			/**
			 * 处理左右移动箭头
			 */
			function triggerDirection(){
				var arrowLeft = $(_this).find(param.arrowLeft),arrowRight = $(_this).find(param.arrowRight),
					arrowLeftOver = param.arrowLeftOver, arrowRightOver = param.arrowRightOver;
				
				arrowLeft.bind({
					click:function(){
						if(index != 0){// 判断当前是不是第一张
							classOper([imgNode,tabNode],defaultClass,false);
							animate();
						}
						return false;
					},
					mouseover:function(){$(this).addClass(arrowLeftOver);},
					mouseout:function(){$(this).removeClass(arrowLeftOver);}
				});
				arrowRight.bind({
					click:function(){
						if(index < imgNode.length - 1){// 判断当前是不是最后一张
							classOper([imgNode,tabNode],defaultClass,true);
							animate();
						}
						return false;
					},
					mouseover:function(){$(this).addClass(arrowRightOver);},
					mouseout:function(){$(this).removeClass(arrowRightOver);}
				});
			}
			
			/**
			 * 透明效果
			 */
			function transparent(){
				imgNode.animate({
					opacity: 0
				  }, 0, function() {
				  });
				$(_this).css({'background-color':imgNode.eq(index).attr('background')});
				imgNode.eq(index).animate({
					opacity: 1
				  }, 1000, function() {
					  _stop();
					  time = setTimeout(imgMove, timer);
				  });
			}
			
			/** 
			 * 移动效果：每一张图片分10次移动
			 */
			function oneImgMove(){
				var nowMoveRange = (index * moveRange) - imgArea[0][scroll],
				partImgRange = nowMoveRange > 0 ? Math.ceil(nowMoveRange / 10) : Math.floor(nowMoveRange / 10);
				imgArea[0][scroll] += partImgRange;
				if (partImgRange == 0){
					imgNode.eq(index).addClass(defaultClass);
					tabNode.eq(index).addClass(defaultClass);
					photoName.text(imgNode.eq(index).find("img").attr("title"));
					partImgRange = null;
					_stop();
					time = setTimeout(imgMove, timer);
				}
				else{
					partTime = setTimeout(oneImgMove,30);	
				}
				$(_this).css({'background-color':imgNode.eq(index).attr('background')});
			}

			/**
			 * 节点css类名操作
			 */ 
			function classOper(arr,className,flag){
				arr.each(function(ind,n){
					n.eq(index).removeClass(className);
				})
				flag?(index++):(index--);
				arr.each(function(ind,n){
					n.eq(index).addClass(className);
				});
			}
		},
		/* 
		 * @function 片段轮播：1、根据用户设置的宽度和高度来确定轮播图的大小。2、可自定义向左、向上轮播和渐变轮播参数。3、可设置轮播时间。
		 * @description 主要应用于html片段轮播，即雷宁轮播模块。此模块和图片轮播功能类似，差异之处在于图片轮播的数据是用户自己上传的图片，html片段轮播每一屏都是一个自定义编辑器，里面的内容全部由用户自定义。
		 * @param：
		 * @author 20130114 by bjwanchuan
		 */
		slideHtml:function(args){
			
			// 定义传入的CSS调用变量
			var _this=this,
				param=$.extend({imgArea:'.jbannerImg', imgNodeArea:'.jImgNodeArea', imgNode:'.jbannerImg li', tabArea:'.jbannerTab', tabNode:'.jbannerTab span', arrowLeft:'.jPreOut', arrowRight:'.jNextOut', arrowLeftOver:'jPreOver', arrowRightOver:'jNextOver', defaultClass:'show', slideDirection:'left', timer:'3', subFunction:'transparentEffect', eventType:'click',showArrow:1}, args),
				imgArea = $(_this).find(param.imgArea),
				imgNode = $(_this).find(param.imgNode),
				tabArea = $(_this).find(param.tabArea),
				tabNode = $(_this).find(param.tabNode),
				photoName = $(_this).find(param.photoName),
				defaultClass = param.defaultClass,
				eventType = param.eventType,
				timer = !param.timer*1000?3000:param.timer*1000,
				scroll,
				ul = $(_this).find(param.imgNodeArea + '>ul'),
				imgNodeArea = $(_this).find(param.imgNodeArea),
				isFull = param.isFull;

			//全局变量
			var index = 0,direction = 1,time = null,moveRange = 0,partTime = null,animate = null;
			if(!imgNode.length) return;
			
			/**
			 * 轮播图所有效果
			 */
			var banner = {
				transparentEffect : function(){
					//初始化
					$(_this).css({'background-color':imgNode.eq(index).attr('background')});
					
					// 调用函数
					init();
					triggerThumbnail();
					triggerDirection();
					if(param.showArrow!=1){triggerArrow();}
					animate = transparent;
					time = setTimeout(imgMove, timer);
				},
				moveEffect : function(){
					var isTop = (param.slideDirection == 'top')?true:false;
					scroll = (isTop)?"scrollTop":"scrollLeft";
					
					//初始化
					$(_this).css({'background-color':imgNode.eq(index).attr('background')});
					if(isTop){
						imgNodeArea.css({height:20000});
						imgNode.css({width:imgNode.attr("width"),height:imgNode.attr("height")});
						moveRange = imgNode.height();
						imgArea[0][scroll] = index * moveRange;
					}else{
						imgNodeArea.css({width:20000});
						imgNode.css({width:imgNode.attr("width"),height:imgNode.attr("height"),'float':"left"});//将这个宽度写在css里，在ie6下面，获取到的父级宽度是被这个元素撑开的宽度
						moveRange = imgNode.width();
						imgArea[0][scroll] = index * moveRange;
					};
					
					// 调用函数
					init();
					triggerThumbnail();
					triggerDirection();	
					if(param.showArrow!=1){triggerArrow();}
					animate = oneImgMove;
					time = setTimeout(imgMove, timer);
				}
			};
			
			/**
			 * 根据传入的子方法名执行对应的子方法
			 */
			if(banner[param.subFunction])
				banner[param.subFunction].call(_this);
			
			/**
			 * 轮播图初始化
			 */
			function init(){
				imgArea.css({width:imgNode.attr("width"),height:imgNode.attr("height")});
				imgNode.eq(0).addClass(defaultClass);
				tabNode.eq(0).addClass(defaultClass);
				autoMiddle();
				$(window).resize(function(){
					autoMiddle();
				});
			}
			
			/**
			 * 轮播图自适应居中于屏幕中间
			 */
			function autoMiddle(){
				var extra = imgArea.width()-$(_this).width();
				if(extra>0){
					imgArea.css({'margin-left':-extra/2});
				}else{
					imgArea.css('margin','0 auto');
				}
			}
			
			/**
			 * 给每个tab缩略图绑定事件
			 */ 
			function triggerThumbnail(){
				tabNode.each(function(i,elem){
					$(elem)[eventType](function(){			   
						imgNode.eq(index).removeClass(defaultClass);
						tabNode.eq(index).removeClass(defaultClass);
						index = i;
						imgNode.eq(index).addClass(defaultClass);
						tabNode.eq(index).addClass(defaultClass);
						animate();
						return false;
					});
				});
			}
			
			/**
			 * 点击箭头或数字时，重置时间
			 */
			function _stop(){
				clearTimeout(time);
				time = null;
				clearTimeout(partTime);
				partTime = null;
				ul.clearQueue();
				imgNode.eq(index).clearQueue();
			}
			
			/**
			 * 切换图片和缩略图
			 */ 
			function imgMove(){
				if (direction == 1){
					if (index < imgNode.length - 1){
						classOper([imgNode,tabNode],defaultClass,true);
					}else{
						direction = 0;
						classOper([imgNode,tabNode],defaultClass,false);
					}
				}else{
					if (index > 0){
						classOper([imgNode,tabNode],defaultClass,false);
					}else{
						direction = 1;
						classOper([imgNode,tabNode],defaultClass,true);
					}
				}
				animate();
			}
			
			/**
			 * 鼠标移动显示左右移动箭头
			 */
			function triggerArrow(){
				var arrowLeft = $(_this).find(param.arrowLeft),arrowRight = $(_this).find(param.arrowRight);
				$(_this).bind({
					mouseover:function(){
						arrowLeft.show();
						arrowRight.show();
					},
					mouseout:function(){
						arrowLeft.hide();
						arrowRight.hide();
					}
				 });
			}
			
			/**
			 * 处理左右移动箭头
			 */
			function triggerDirection(){
				var arrowLeft = $(_this).find(param.arrowLeft),arrowRight = $(_this).find(param.arrowRight),
					arrowLeftOver = param.arrowLeftOver, arrowRightOver = param.arrowRightOver;
				
				arrowLeft.bind({
					click:function(){
						if(index != 0){// 判断当前是不是第一张
							classOper([imgNode,tabNode],defaultClass,false);
							animate();
						}
						return false;
					},
					mouseover:function(){$(this).addClass(arrowLeftOver);},
					mouseout:function(){$(this).removeClass(arrowLeftOver);}
				});
				arrowRight.bind({
					click:function(){
						if(index < imgNode.length - 1){// 判断当前是不是最后一张
							classOper([imgNode,tabNode],defaultClass,true);
							animate();
						}
						return false;
					},
					mouseover:function(){$(this).addClass(arrowRightOver);},
					mouseout:function(){$(this).removeClass(arrowRightOver);}
				});
			}
			
			/**
			 * 透明效果
			 */
			function transparent(){
				imgNode.animate({
					opacity: 0
				  }, 0, function() {
				  });
				$(_this).css({'background-color':imgNode.eq(index).attr('background')});
				imgNode.eq(index).animate({
					opacity: 1
				  }, 1000, function() {
					  _stop();
					  time = setTimeout(imgMove, timer);
				  });
				
			}
			
			/** 
			 * 移动效果：每一张图片分10次移动
			 */
			function oneImgMove(){
				var nowMoveRange = (index * moveRange) - imgArea[0][scroll],
				partImgRange = nowMoveRange > 0 ? Math.ceil(nowMoveRange / 10) : Math.floor(nowMoveRange / 10);
				imgArea[0][scroll] += partImgRange;
				if (partImgRange == 0){
					imgNode.eq(index).addClass(defaultClass);
					tabNode.eq(index).addClass(defaultClass);
					partImgRange = null;
					_stop();
					time = setTimeout(imgMove, timer);
				}
				else{
					partTime = setTimeout(oneImgMove,30);	
				}
				$(_this).css({'background-color':imgNode.eq(index).attr('background')});
			}

			/**
			 * 节点css类名操作
			 */ 
			function classOper(arr,className,flag){
				arr.each(function(ind,n){
					n.eq(index).removeClass(className);
				})
				flag?(index++):(index--);
				arr.each(function(ind,n){
					n.eq(index).addClass(className);
				});
			}
		},
		/*
		 * @function：改变图片：事件触发小图查看大图。
		 * @description：主要应用于商品推荐、主从商品等模块，能取到同一张不同尺寸大小的图片，这样就可以实现事件触发小图查看大图的效果。
		 * @param：
		 * @author：20130114 by bjwanchuan
		 */
		changePhoto : function(args){
			var param = $.extend({changePhotoNode:'.jPic img' , smallPhoto:'.jScrollWrap li', title:'.jDesc a', defaultClass:'jCurrent', eventType:'click'} , args || {}),
				_this = $(this),
				largePhoto = _this.find(param.changePhotoNode),
				smallPhoto = _this.find(param.smallPhoto),
				title = _this.find(param.title);
			
			//初始化
			largePhoto.attr('src' , smallPhoto.eq(0).attr('data-src'));
			largePhoto.parent().attr('href' , smallPhoto.eq(0).attr('data-href'));
			title.attr('href' , smallPhoto.eq(0).attr('data-href'));
			
			smallPhoto.eq(0).addClass(param.defaultClass);
			
			//触发小图
			smallPhoto[param.eventType](function(){
				var _target = this;
				
				largePhoto.attr('src' , $(_target).attr('data-src'));
				largePhoto.parent().attr('href' , $(_target).attr('data-href'));
				title.attr('href' , $(_target).attr('data-href'));
				
				//切换大图的时候 同时切换关注商品的input 结点ID
				var goodsFollow = $(_target).parents("li.jSubObject");
				if( typeof goodsFollow != "undefined" && typeof $(_target).attr('sid') != "undefined" ){
					var btnColl = jQuery(goodsFollow).find(".btn-coll");
					if( typeof btnColl.attr('id') != "undefined" ){
						btnColl.attr('id',"coll"+ $(_target).attr('sid') );
					}	
				}
				
				$(_target).addClass(param.defaultClass).siblings().removeClass(param.defaultClass);
			});
		},
		/*
		 * @function：移动图片：点击左右箭头移动图片。
		 * @description：主要应用于主从商品等模块，当容器宽度有限，图片却很多时，点击左右箭头就可移动图片。
		 * @param：
		 * @author：20130114 by bjwanchuan
		 */
		movePhoto : function(args){
			var param = $.extend({movePhotoNode:'.jScrollWrap li' , arrowPrev:'.jScrollPrev', arrowNext:'.jScrollNext', defaultClass:'disabled'} , args || {}),
				_this = $(this),
				node = _this.find(param.movePhotoNode),
				prev = _this.find(param.arrowPrev),
				next = _this.find(param.arrowNext),
				visibleNode = parseInt(node.parent().parent().width()/node.width()),
				index = 0,
				length = node.length;
			
			//初始化结构
			if(length > visibleNode){
				prev.addClass(param.defaultClass).show();
				next.show();
				node.parent().css('width',node.width()*length);
			}
			
			//向右移动
			next.click(function(){
				var _this = this;
				
				if(length - visibleNode){
					prev.removeClass(param.defaultClass);
				}
				
				if(index < length - visibleNode){
					index++;
					node.parent().animate({
						left:-node.eq(0).outerWidth(true)*index
					},function(){
						if(index + visibleNode == length){
							$(_this).addClass(param.defaultClass);
						}
					});
				}
			});
			
			//向左移动
			prev.click(function(){	
				var _this = this;
				if(index  + visibleNode <= length){
					next.removeClass(param.defaultClass);
				}

				if(index > 0){
					index--;
					node.parent().animate({
						left:-node.eq(0).outerWidth(true)*index
					},function(){
						if(!index){
							$(_this).addClass(param.defaultClass);
						}
					});
				}
			});	
		},
		/*
		 * @function：操作节点：通过不同的条件，调用不同的方法，查找对象里面的某一个或一些节点，并对这些节点做操作，默认为增加一个样式。
		 * @description：可应用于任意模块，只要有使用场景。
		 * @param：如{operateNode:'li', operateParentNode:null, defaultClass:'jCurrent', length:0, subFunction:null, number:[], callBack:null}
		 * operateNode为需要查找的节点；operateParentNode为查找节点的父级节点；defaultClass为默认样式名；length为每一行的节点个数；subFunction为此方法里面的子方法；
		 * number为数组对象，当使用getNode方法时，表示数组里面指定的节点，当使用getColumn方法时，表示指定的列节点。当使用getRow方法时，表示指定的行节点；
		 * callBack为函数体，参数接收一个节点对象，可在函数体里对接收的这个对象做操作。
		 * @author：20130114 by bjwanchuan
		 */
		operateNode: function(args){
			var param = $.extend({operateNode:'li', operateParentNode:null, defaultClass:'jCurrent', length:0, subFunction:null, number:[], callBack:null},args||{}),
			_this = $(this),
			node = _this.find(param.operateNode),
			nodeParent = (_this.find(param.operateParentNode).length > 0) ? _this.find(param.operateParentNode) : _this.parent().parent().parent(),
			defaultClass = param.defaultClass,
			number = param.number,
			length = (param.length != 0) ? param.length : parseInt(nodeParent.outerWidth(true)/node.outerWidth(true)),
			callBack = typeof(param.callBack) === 'function' ? param.callBack : function(a){a.addClass(defaultClass);};
		
			if(node.length === 0) return;
			
			//ie9下获取nodeParent.outerWidth(true)有差异。为避免此问题，1、可传入明确知道宽度的节点；2、程序会取this的父级的父级的父级定义了宽度的层。
			//此段尚未使用，当元素隐藏后获取不到元素的偏移值
			var rowLen = 0;
			var nowTop = $(node[0]).offset().top;
			node.each(function(index, dom){
				if(index > 0){
					rowLen++;
					var _top = $(dom).offset().top;
					if(nowTop !== _top){
						return false;
					}else{
						nowTop = _top;
					}
				}
			});
			
			var operate = {
				//获取任意节点
				getNode : function(){
					return node.map(function(i,e){
						for(var j = 0; j < number.length; j++){
							if(i + 1 === number[j]){
								return e;
							}
						}
					});
				},
				//获取所有奇数列节点
				getAllOdd : function (){
					return node.map(function(i, e){
						if(i % 2 === 0){
							return e;
						}
					})
				},
				//获取所有偶数列节点
				getAllEven : function(){
					return node.map(function(i,e){
						if(i % 2 === 1){
							return e;
						}
					});
				},
				//获取任意多列节点
				getColumn : function(){
					return node.map(function(i,e){
						for(var j = 0; j < number.length; j++){
							if(i % length === number[j] - 1){
								return e;
							}
						}
					});
				},
				//获取任意多行节点
				getRow : function(){
					return node.map(function(i,e){
						for(var j = 0; j < number.length; j++){
							if(i >= length * (number[j] - 1) && i < length * number[j]){
								return e;
							}
						}
					});
				},
				//获取每一行的奇数节点
				getRowOdd : function(){
					return node.map(function(i,e){
						if(i % length % 2 === 0){
							return e;
						}
					});
				},
				//获取每一行的偶数节点
				getRowEven : function(){
					return node.map(function(i,e){
						if(i % length % 2 === 1){
							return e;
						}
					});
				},
				//获取第一个节点
				getFirst : function(){
					return node.eq(0);
				},
				//获取最后一个节点
				getLast : function(){
					return node.eq(node.length - 1);
				},
				//获取每一行的第一个节点
				getRowFirst : function(){
					return node.map(function(i,e){
						if(i % length === 0){
							return e;
						}
					});
				},
				//获取每一行的最后一个节点
				getRowLast : function(){
					return node.map(function(i,e){
						if(i % length === length - 1){
							return e;
						}
					});
				},
				//获取每一行的第一个节点和最后一个节点
				getRowFirstAndLast : function(){
					return node.map(function(i,e){
						if(i % length === 0 || i % length === length - 1){
							return e;
						}
					});
				}
			}
			
			if(operate[param.subFunction]){
				callBack(operate[param.subFunction]());
			}
		},
		/*
		 * @function： 移动节点
		 * @description：点击左右箭头移动节点，可移动单个节点，也可移动一屏节点，可左右移动，也可左右循环移动
		 * @param：moveNode需要移动的节点；arrowPrev左箭头；arrowNext右箭头；disabled箭头不可用样式；showNum一屏显示数量，可传入正确的一屏数量，没传则程序计算；
					cssValue改变的css属性名；isLoop是否循环，默认为真；isScreen是否是移动一屏，默认为真；timer每一次移动的时间，默认为1，值取0-4之间。
		 * @note：如果是移动一屏，则需要的节点总数量必须为每一屏可显示的整数倍；如果是循环切换，disabled参数可不用。
		 * @author： cdwanchuan@jd.com 2014-03
		*/
		moveNode : function(args){
			var param = $.extend({moveNode:'.scroll-area li' , arrowPrev:'.arrow-left', arrowNext:'.arrow-right', disabled:'disabled', showNum:'', cssValue:'margin-left', isLoop:true, isScreen:true, timer:1} , args || {}),
				_this = $(this),
				node = _this.find(param.moveNode),
				prev = _this.find(param.arrowPrev),
				next = _this.find(param.arrowNext),
				showNum = (param.showNum> 0)? parseInt(param.showNum) : Math.ceil(node.parent().parent().width()/node.outerWidth(true)),
				index = 0,
				length = param.isScreen ? Math.ceil(node.length/showNum) : node.length,
				eventFlag = true,
				moveWidth = param.isScreen ? showNum*node.eq(0).outerWidth(true) : node.eq(0).outerWidth(true),
				visibleNum = param.isScreen ? 1 : showNum,
				timer = !(param.timer > -1 && param.timer < 5) ? 1000 : param.timer*1000;
			
			if(length > visibleNum){
				prev.show().addClass(param.disabled);
				next.show();
				node.parent().css('width',moveWidth*length*10);
				
				if(param.isLoop){initLoop();}
			}
			
			function initLoop(){
				for(var i=0; i<showNum; i++){
					node.eq(i).clone().appendTo(node.parent());
					node.eq(node.length-1-i).clone().prependTo(node.parent());
				}
				node.parent().css(param.cssValue,-moveWidth*visibleNum + parseInt(node.parent().css(param.cssValue)));	
			}
			
			var cssJson = {};
			node.parent().data('cssInitValue', parseInt(node.parent().css(param.cssValue)));
			
			next.click(function(){
				if(!param.isLoop){
					if(index == 0) eventFlag = true;
				}
				
				if(eventFlag){
					eventFlag = false;
					index++;
					cssJson[param.cssValue] = -moveWidth*index + node.parent().data('cssInitValue');
					
					node.parent().animate(cssJson, timer, function(){
						eventFlag = true;
						if(!param.isLoop){
							if(index > 0){
								prev.removeClass(param.disabled);
							}
							if(index+visibleNum == length){
								next.addClass(param.disabled);
								eventFlag = false;
							}
						}else{
							if(index == length){
								index = 0;
								node.parent().css(param.cssValue,node.parent().data('cssInitValue'));	
							}
						}
					});
				}
			});
			
			prev.click(function(){
				if(!param.isLoop){
					eventFlag = (index > 0) ? true :false;
				}
				
				if(eventFlag){
					eventFlag = false;
					index--;
					cssJson[param.cssValue] = -moveWidth*index + node.parent().data('cssInitValue');
					
					node.parent().animate(cssJson, timer, function(){
						eventFlag = true;
						if(!param.isLoop){
							if(index < length - 1){
								next.removeClass(param.disabled);
							}
							if(index == 0){
								prev.addClass(param.disabled);
								eventFlag = false;
							}
						}else{
							if(index < 0){
								index = length-1;
								node.parent().css(param.cssValue,node.parent().data('cssInitValue')+(-moveWidth*index));	
							}
						}
					});
				}
			});	
		},
		/*
		 * @function：多行省略号 ：计算文字的数量，超过一定的数量后，剩余的用其他传入的字符替换。
		 * @description：主要应用于商品展示类模块中，如商品推荐、分页显示商品、店内搜索结果、主从商品等等模块，当商品标题太长而布局容器有限时使用。
		 * @param：如{title:'.jDesc a', count:15, text:'...'}。title需要替换的文字节点；count文字的数量；text用于替换的字符；
		 * @author：20130114 by bjwanchuan
		 */
		addEllipsis:function(args){
		   var param = $.extend({title:'.jDesc a', count:15, text:'...'}, args),
		   		_this = $(this),
				elem = _this.find(param.title);
		   
			elem.each(function(index, ele){
				var textNode=ele.firstChild;
				if(textNode && textNode.nodeType==3 && textNode.length>=param.count){
					textNode.replaceData(param.count, textNode.length, param.text);
				}					   
			});
	   },
		shopSearch : function(args){
			jshop.module.search.shopSearch.call(this,args);
		},
		follow : (function(){
			    // 默认参数设置
		

			function newTagOnfocus() {
				var val = jQuery("#newTag").val();
				val = val.trim();
				if (val == jQuery("#newTag").attr("placeholder")) {
					jQuery("#newTag").val("");
				}
			}

			function checkLength(node) {
				if (node.value.length > 10) {
					node.value = node.value.substring(0, 10);
				}
			}


			function Follow(cfg,scope) {
				this.config = jQuery.extend({}, cfg);

				var config = jQuery.extend({}, this.config);
				this.container = $(config.node,scope);

				this.get = function(p) {
					return config[p];
				};
				this.set = function(p, v) {
					config[p] = v;
				};

				this.init();
			}

			Follow.FollowVMContent = '';


			
			return function(arg){
				var cfg = $.extend({},_default,arg);
				new Follow(cfg,$(this));
			}
		})()
	});
	
	
	function _execute(module){
		var _function = $(module).attr('module-function'),
			_module_name = $(module).parents('[module-name]').attr('module-name'), _param;
		if(typeof _function == 'undefined') return;
		try{
			_param = eval('(' + $(module).attr('module-param') + ')');
		}catch(e){
			_param = {};
		}
		var _functions = _function.split(',');
		_functions.each(function(index,n){
			if(jshop.module[_module_name]&&jshop.module[_module_name][n]){
				if(_param.subObj){
					$(module).find(_param.subObj).each(function(ind,q){
						jshop.module[_module_name][n].call(q,_param);
					});
				}
				else{
					jshop.module[_module_name][n].call(module,_param);
				}
			}
			else if(jshop.module[n]){
				if(_param.subObj){
					$(module).find(_param.subObj).each(function(ind,q){
						jshop.module[n].call(q,_param);
					});
				}
				else{
					jshop.module[n].call(module,_param);
				}
			}
		});
	}
	$(function(){			
		$('div.j-module').each(function(index,n){
			if(!$(n).attr('panda')){
				_execute(n);
			}
		});
	});
	
	/*
	 * 局部刷新逻辑
	 */
	w.moduleRefresh = function(){
		var _this = $(this);
		_this.each(function(index,n){
			_execute(n);
		});
	};
})(jQuery,window);
